//
// Created by WangPeng on 24-8-19.
//

#include "aac_file.h"

#include <utility>
#include <iostream>
#include <cstring>

#include "../socket/udp_sk.h"
#include "../rtsp_protocol/rtp_protocol.h"

//音频ACC，ADTS格式头
struct adts_header
{
    unsigned int syncword;  //12 bit 同步字 '1111 1111 1111'，一个ADTS帧的开始
    uint8_t id;        //1 bit 0代表MPEG-4, 1代表MPEG-2。
    uint8_t layer;     //2 bit 必须为0
    uint8_t protection_absent;  //1 bit 1代表没有CRC，0代表有CRC //以上2个字节 16位
    uint8_t profile;           //1 bit AAC级别（MPEG-2 AAC中定义了3种profile，MPEG-4 AAC中定义了6种profile）
    uint8_t sampling_freq_index; //4 bit 采样率
    uint8_t private_bit;        //1bit 编码时设置为0，解码时忽略
    uint8_t channel_cfg;        //3 bit 声道数量 //9bit
    uint8_t original_copy;      //1bit 编码时设置为0，解码时忽略
    uint8_t home;               //1 bit 编码时设置为0，解码时忽略

    uint8_t copyright_identification_bit;   //1 bit 编码时设置为0，解码时忽略
    uint8_t copyright_identification_stat; //1 bit 编码时设置为0，解码时忽略 //4bits
    unsigned int aac_frame_length;               //13 bit 一个ADTS帧的长度包括ADTS头和AAC原始流 //26位
    unsigned int adts_buffer_fullness;           //11 bit 缓冲区充满度，0x7FF说明是码率可变的码流，不需要此字段。CBR可能需要此字段，不同编码器使用情况不同。这个在使用音频编码的时候需要注意。

    /* number_of_raw_data_blocks_in_frame
     * 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧
     * 所以说number_of_raw_data_blocks_in_frame == 0
     * 表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
     */
    uint8_t number_of_raw_data_block_in_frame; //2 bit
};

CAACFile::CAACFile(std::string file_name) : CAbstractInterface(std::move(file_name))
{
    ifs_.open(file_name_, std::ios::binary);
    if (!ifs_)
    {
        std::cerr << "the file {" << file_name_ << "} open fail!" << std::endl;
        return;
    }
}

CAACFile::~CAACFile() = default;

long CAACFile::get_frame_data(char *&frame, long size)
{
    if (!ifs_.read((char*)frame, size))
    {
        return -1;
    }
    long read_size = ifs_.gcount();
    std::cout << "read_size = " << read_size << std::endl;
    //解析并获取adts头部
    struct adts_header header{};
    if (parse_adts_header(reinterpret_cast<uint8_t*>(frame), &header) < 0)
    {
        std::cerr << "parse_adts_header failer!" << std::endl;
        return -1;
    }
    //根据头部，获取音频帧数据
    if (!ifs_.read((char*)frame, header.aac_frame_length - 7))
    {
        std::cerr << "read audio frame error" << std::endl;
        return -1;
    }
    read_size = ifs_.gcount();
    std::cout << "read audio frame size = " << read_size << ", frame length = " << (header.aac_frame_length - 7) << std::endl;
    return (header.aac_frame_length - 7);
}

int CAACFile::parse_adts_header(const uint8_t *input, struct adts_header *header)
{
    memset(header, 0, sizeof(*header));

    if ((input[0] == 0xFF) && ((input[1] & 0xF0) == 0xF0))
    {
        header->id = ((uint8_t)input[1] & 0x08) >> 3;//第二个字节与0x08与运算之后，获得第13位bit对应的值
        header->layer = ((uint8_t)input[1] & 0x06) >> 1;//第二个字节与0x06与运算之后，右移1位，获得第14,15位两个bit对应的值
        header->protection_absent = (uint8_t)input[1] & 0x01;
        header->profile = ((uint8_t)input[2] & 0xc0) >> 6;
        header->sampling_freq_index = ((uint8_t)input[2] & 0x3c) >> 2;
        header->private_bit = ((uint8_t)input[2] & 0x02) >> 1;
        header->channel_cfg = ((((uint8_t)input[2] & 0x01) << 2) | (((unsigned int)input[3] & 0xc0) >> 6));
        header->original_copy = ((uint8_t)input[3] & 0x20) >> 5;
        header->home = ((uint8_t)input[3] & 0x10) >> 4;
        header->copyright_identification_bit = ((uint8_t)input[3] & 0x08) >> 3;
        header->copyright_identification_stat = (uint8_t)input[3] & 0x04 >> 2;

        header->aac_frame_length = (((((unsigned int)input[3]) & 0x03) << 11) |
                               (((unsigned int)input[4] & 0xFF) << 3) |
                               ((unsigned int)input[5] & 0xE0) >> 5);

        header->adts_buffer_fullness = (((unsigned int)input[5] & 0x1f) << 6 |
                                   ((unsigned int)input[6] & 0xfc) >> 2);
        header->number_of_raw_data_block_in_frame = ((uint8_t)input[6] & 0x03);

        return 0;
    }
    else
    {
        printf("failed to parse adts header\n");
        return -1;
    }
}

void CAACFile::play(CUdpSocket *udp_socket, CRtpProtocol* rtp_protocol)
{
    char* frame = (char *)::malloc(5000);
    while (true)
    {
        long frame_size = get_frame_data(frame, 7);
        if (frame_size < 0)
        {
            break;
        }
        send_aac_stream_over_udp(udp_socket, rtp_protocol, frame, frame_size);
        usleep(23223);
    }
    ::free(frame);
}

int CAACFile::send_aac_stream_over_udp(CUdpSocket *udp_socket, CRtpProtocol* rtp_protocol,
                                       char *frame, std::size_t frame_size)
{
    struct RtpPacket* rtp_packet = rtp_protocol->get_packet();

    rtp_packet->payload[0] = 0x00;
    rtp_packet->payload[1] = 0x10;
    rtp_packet->payload[2] = (frame_size & 0x1FE0) >> 5; //高8位
    rtp_packet->payload[3] = (frame_size & 0x1F) << 3; //低5位

    memcpy(rtp_packet->payload + 4, frame, frame_size);

    int ret = CRtpProtocol::send_rtp_over_udp(udp_socket, rtp_packet, frame_size + 4);
    if (ret < 0)
    {
        printf("failed to send rtp packet\n");
        return -1;
    }

    rtp_packet->hrtp.seq++;

    /*
     * 如果采样频率是44100
     * 一般AAC每个1024个采样为一帧
     * 所以一秒就有 44100 / 1024 = 43帧
     * 时间增量就是 44100 / 43 = 1025
     * 一帧的时间为 1 / 43 = 23ms
     */
    rtp_packet->hrtp.timestamp += 1025;

    return 0;
}
